package com.bpf.base.util;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

public class MapUtil extends MapUtils {

	private final static Logger logger = LoggerFactory.getLogger(MapUtil.class);

	public static <T> T toObject(Class<T> clazz, Map<String, Object> map) throws InstantiationException, IllegalAccessException {
		T object = clazz.newInstance();
		toObject(clazz, object, map);
		return object;
	}

	private static void toObject(Class<?> clazz, Object object, Map<String, Object> map) {
		Method[] methods = clazz.getDeclaredMethods();
		if (methods != null && methods.length > 0) {
			for (Method method : methods) {
				String mname = method.getName();
				if (mname.startsWith("set") && method.getParameterTypes().length == 1) {
					try {
						Class<?> fieldType = method.getParameterTypes()[0];
						String fname = mname.substring(3, 4).toLowerCase() + mname.substring(4);
						Object fieldValue = map.get(fname);
						if (fieldValue != null) {
							if (String.class.equals(fieldType)) {
								method.invoke(object, fieldValue);
							} else if (Integer.class.equals(fieldType)) {
								method.invoke(object, Integer.valueOf( fieldValue.toString()));
							} else if (Long.class.equals(fieldType)) {
								method.invoke(object, Long.valueOf((String) fieldValue.toString()));
							} else if (Boolean.class.equals(fieldType)) {
								if ("true".equalsIgnoreCase(fieldValue.toString())) {
									method.invoke(object, Boolean.TRUE);
								} else {
									method.invoke(object, Boolean.FALSE);
								}
							} else if (Map.class.equals(fieldType)) {
								if (!String.class.equals(fieldValue.getClass())) {
									method.invoke(object, fieldValue);
								}
							} else if (byte[].class.equals(fieldType)) {
								if (!((MultipartFile) fieldValue).isEmpty()) {
									try {
										method.invoke(object, ((MultipartFile) fieldValue).getBytes());
									} catch (Exception e) {
										logger.error(e.getMessage(), e);
									}
								}

							} else {
								method.invoke(object, fieldValue);
							}
						}
					} catch (IllegalAccessException e) {
						logger.error(e.getMessage(), e);
					} catch (InvocationTargetException e) {
						logger.error(e.getMessage(), e);
					} catch (SecurityException e) {
						logger.error(e.getMessage(), e);
					}
				}
			}
		}
		// java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
		// if (fields != null && fields.length > 0) {
		// for (int i = 0; i < fields.length; i++) {
		// try {
		// Class<?> fieldType = fields[i].getType();
		// String fieldName = fields[i].getName();
		// Object fieldValue = map.get(fieldName);
		// if (fieldValue != null) {
		// String setFieldName = "set" + fieldName.substring(0, 1).toUpperCase()
		// + fieldName.substring(1);
		// Method method = clazz.getMethod(setFieldName, fieldType);
		// if (String.class.equals(fieldValue)) {
		// method.invoke(object, fieldValue);
		// } else if (Integer.class.equals(fieldType)) {
		// method.invoke(object, Integer.valueOf((String)fieldValue));
		// } else if (Long.class.equals(fieldType)) {
		// method.invoke(object, Long.valueOf((String)fieldValue));
		// } else if (Boolean.class.equals(fieldType)) {
		// if ("true".equalsIgnoreCase((String)fieldValue)) {
		// method.invoke(object, Boolean.TRUE);
		// } else {
		// method.invoke(object, Boolean.FALSE);
		// }
		// } else if (Map.class.equals(fieldType)) {
		// if (!String.class.equals(fieldValue.getClass())) {
		// method.invoke(object, fieldValue);
		// }
		// } else {
		// method.invoke(object, fieldValue);
		// }
		// }
		// } catch (IllegalAccessException e) {
		// logger.error(e.getMessage(), e);
		// } catch (InvocationTargetException e) {
		// logger.error(e.getMessage(), e);
		// } catch (SecurityException e) {
		// logger.error(e.getMessage(), e);
		// } catch (NoSuchMethodException e) {
		// logger.error(e.getMessage(), e);
		// }
		// }
		// }
		if (clazz.getSuperclass() != null) {
			toObject(clazz.getSuperclass(), object, map);
		}
	}

	@SuppressWarnings("rawtypes")
	public static List<Map<String, Object>> toMapList(Collection collection) {
		List<Map<String, Object>> retList = new ArrayList<Map<String, Object>>();
		if (collection != null && !collection.isEmpty()) {
			for (Object object : collection) {
				Map<String, Object> map = new HashMap<String, Object>();
				toMap(object.getClass(), object, map);
				retList.add(map);
			}
		}
		return retList;
	}

	public static Map<String, Object> toMap(Object object) {
		Map<String, Object> map = new HashMap<String, Object>();
		toMap(object.getClass(), object, map);
		return map;
	}

	private static void toMap(Class<?> clazz, Object object, Map<String, Object> map) {
		Method[] methods = clazz.getDeclaredMethods();
		if (methods != null && methods.length > 0) {
			for (Method method : methods) {
				String mname = method.getName();
				if (mname.startsWith("get") && method.getParameterTypes().length == 0) {
					try {
						String fieldName = mname.substring(3, 4).toLowerCase() + mname.substring(4);
						if ("serialVersionUID".equals(fieldName)) {
							continue;
						} else if ("class".equals(fieldName)) {
							continue;
						}
						Object fieldValue = method.invoke(object, null);
						if (fieldValue != null) {
							map.put(fieldName, fieldValue);
						}
					} catch (IllegalAccessException e) {
						logger.error(e.getMessage(), e);
					} catch (InvocationTargetException e) {
						logger.error(e.getMessage(), e);
					} catch (SecurityException e) {
						logger.error(e.getMessage(), e);
					}
				}
			}
		}

		// java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
		// if (fields != null && fields.length > 0) {
		// for (int i = 0; i < fields.length; i++) {
		// try {
		// String fieldName = fields[i].getName();
		// if ("serialVersionUID".equals(fieldName)) {
		// continue;
		// }
		// String fieldValue = BeanUtils.getProperty(object, fieldName);
		// if (fieldValue != null) {
		// map.put(fieldName, fieldValue);
		// }
		// } catch (IllegalAccessException e) {
		// logger.error(e.getMessage(), e);
		// } catch (InvocationTargetException e) {
		// logger.error(e.getMessage(), e);
		// } catch (NoSuchMethodException e) {
		// logger.error(e.getMessage(), e);
		// }
		// }
		// }
		if (clazz.getSuperclass() != null) {
			toMap(clazz.getSuperclass(), object, map);
		}
	}

	/**
	 * 将后面一个Map合并到前面一个Map中，合并过程中如果有重复的将忽略
	 * 
	 * @return
	 */
	public static Map<String, Object> mergeMap(Map<String, Object> mainMap, Map<String, Object> subMap) {
		for (Entry<String, Object> entry : subMap.entrySet()) {
			if (!mainMap.containsKey(entry.getKey())) {
				mainMap.put(entry.getKey(), entry.getValue());
			}
		}
		return mainMap;
	}
}